<h1 id="u语言中间代码设计文档">U语言中间代码设计文档</h1>
<h2 id="前置描述">前置描述</h2>
<p>本文档描述了U语言中间代码（以下简称ir），用VS Code + 扩展（Markdown
Preview Enhanced）编写</p>
<h2 id="目录">目录</h2>
<p><a href="#1">定义</a> <a href="#2">操作数类型</a> <a
href="#3">指令目录</a> - <a href="#4">运算类指令</a> - <a
href="#5">add</a> - <a href="#6">sub</a> - <a href="#7">传输类指令</a> -
<a href="#8">mov</a> - <a href="#9">附录</a></p>
<h2 id="1">
定义
</h2>
<blockquote>
<p>ir是四元式、线性的中间代码 go语言代码表示为</p>
</blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// OPEnum 指令枚举</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> OPEnum <span class="dt">int</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">// ArgEnum 操作数枚举</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> ArgEnum <span class="dt">int8</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="co">// IrNode 代表一条ir指令</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> IrNode <span class="kw">struct</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">//操作码</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    Op OPEnum</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">//第一运算操作数，第二运算操作数，运算结果的值及类型。</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>    Arg1Obj<span class="op">,</span> Arg2Obj<span class="op">,</span> ResultObj <span class="dt">string</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>    Arg1Typ<span class="op">,</span> Arg2Typ<span class="op">,</span> ResultTyp ArgEnum</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="2">
操作数类型
</h2>
<blockquote>
<p>ir目前定义了下列8种操作数类型</p>
</blockquote>
<ul>
<li>NoArg 未定义的操作数</li>
<li>StackVar 栈变量</li>
<li>Var 全局变量</li>
<li>Tmp 临时变量</li>
<li>TmpIntVar int型临时变量,必须编译期可求值</li>
<li>TmpFloatVar float型临时变量,必须编译期可求值</li>
<li>ImmInt int型立即数</li>
<li>ImmFloat float型立即数</li>
</ul>
<h2 id="3">
指令目录
</h2>
<h2 id="4">
运算类指令
</h2>
<h3 id="5">
add
</h3>
<p>指令格式 add &lt;src1,src2,result&gt; 指令操作
将src1和src2相加，结果送入result</p>
<h3 id="6">
sub
</h3>
<p>指令格式 sub &lt;src1,src2,result&gt; 指令操作
将src1和src2相减，结果送入result</p>
<h2 id="7">
传输类指令
</h2>
<h3 id="8">
mov
</h3>
<p>指令格式 mov &lt;src1,_,result&gt; 指令操作 将src1的值送入result</p>
<h2 id="9">
附录
</h2>
<h3 id="10">
官方生成ir指令的优化
</h3>
<blockquote>
<p>官方生成的ir指令有下列优化</p>
</blockquote>
<blockquote>
<p>优化1：如果算术表达式的操作数都是立即数（也就是编译期可求值），直接计算该立即数，不等到运行时计算
&gt;例如 &gt;add &lt;1,2,tmp1&gt; 被优化为 add &lt;noarg,noarg,tmp1&gt;
同时 tmp1=3</p>
</blockquote>
<blockquote>
<p>优化2：如果结果为立即数临时变量（也就是编译期可求值），直接使用该立即数，不等到运行时计算<br />
&gt; 例如 &gt; add &lt;noarg,noarg,tmp1&gt; mov &lt;tmp1,noarg,b&gt;
同时 tmp1因为优化1值为3 &gt; 被优化为 mov &lt; 3,noarg,b&gt;</p>
</blockquote>
<blockquote>
<p>优化3：如果赋值源操作数类型为临时变量，且这个临时变量为上一个的结果，将上一个的结果改写为赋值目的操作数
&gt;例如 &gt; add &lt;b,2,tmp1&gt; mov &lt;tmp1,noarg,b&gt; &gt;
被优化为 add &lt;b,2,b&gt;</p>
</blockquote>
<blockquote>
<p>优化4：如果其中任意两条中间代码形如(a op1 b) op2
c,且b和c为立即数，同时op1和op2优先级相同，改写为a op1 (b op2
c)，并编译期求值 &gt;例如 &gt; add &lt;b,9,tmp1&gt; add &lt;tmp1,1,b&gt;
&gt; 被优化为 add &lt;b,10,b&gt;</p>
</blockquote>
